package health

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"time"

	"mcp-server/internal/config"
)

// BootstrapChecker 启动状态校验器
type BootstrapChecker struct {
	configPath  string
	projectRoot string
	logger      *log.Logger
	startTime   time.Time
}

// BootstrapStatus 启动状态
type BootstrapStatus struct {
	StartTime       time.Time         `json:"start_time"`
	Duration        time.Duration     `json:"duration"`
	System          *SystemStatus     `json:"system"`
	Dependencies    *DependencyStatus `json:"dependencies"`
	Config          *ConfigStatus     `json:"config"`
	PortCheck       *PortCheckStatus  `json:"port_check"`
	DatabaseCheck   *DatabaseStatus   `json:"database_check"`
	Overall         CheckStatus       `json:"overall"`
	ReadyToStart    bool              `json:"ready_to_start"`
	Recommendations []string          `json:"recommendations"`
}

// PortCheckStatus 端口检查状态
type PortCheckStatus struct {
	RequestedPort int           `json:"requested_port"`
	FinalPort     int           `json:"final_port"`
	Available     bool          `json:"available"`
	AutoResolved  bool          `json:"auto_resolved"`
	Checks        []CheckResult `json:"checks"`
	Overall       CheckStatus   `json:"overall"`
}

// DatabaseStatus 数据库状态
type DatabaseStatus struct {
	Initialized   bool          `json:"initialized"`
	DataPath      string        `json:"data_path"`
	DiskSpaceOK   bool          `json:"disk_space_ok"`
	PermissionsOK bool          `json:"permissions_ok"`
	ConnectionOK  bool          `json:"connection_ok"`
	Checks        []CheckResult `json:"checks"`
	Overall       CheckStatus   `json:"overall"`
}

// NewBootstrapChecker 创建启动检查器
func NewBootstrapChecker(configPath, projectRoot string) *BootstrapChecker {
	return &BootstrapChecker{
		configPath:  configPath,
		projectRoot: projectRoot,
		logger:      log.New(os.Stdout, "[BOOTSTRAP] ", log.LstdFlags),
		startTime:   time.Now(),
	}
}

// RunBootstrapChecks 运行启动检查
func (bc *BootstrapChecker) RunBootstrapChecks() *BootstrapStatus {
	bc.logger.Println("开始启动状态校验...")

	status := &BootstrapStatus{
		StartTime:       bc.startTime,
		Recommendations: []string{},
	}

	// 1. 系统环境检查
	bc.logger.Println("检查系统环境...")
	systemChecker := NewSystemChecker()
	status.System = systemChecker.CheckSystem()
	bc.logCheckResults("系统环境", status.System.Checks)

	// 2. 依赖检查
	bc.logger.Println("检查项目依赖...")
	depChecker := NewDependencyChecker(bc.projectRoot)
	status.Dependencies = depChecker.CheckDependencies()
	bc.logCheckResults("项目依赖", status.Dependencies.Checks)

	// 3. 配置文件检查
	bc.logger.Println("检查配置文件...")
	configChecker := NewConfigChecker(bc.configPath)
	status.Config = configChecker.CheckConfig()
	bc.logCheckResults("配置文件", status.Config.Checks)

	// 4. 端口可用性检查
	bc.logger.Println("检查端口可用性...")
	status.PortCheck = bc.checkPortAvailability(status.Config)

	// 5. 数据库初始化检查
	bc.logger.Println("检查数据库初始化...")
	status.DatabaseCheck = bc.checkDatabaseInitialization(status.Config)

	// 6. 计算总体状态和建议
	bc.calculateOverallStatus(status)
	bc.generateRecommendations(status)

	status.Duration = time.Since(bc.startTime)
	bc.logger.Printf("启动状态校验完成，耗时: %v", status.Duration)

	return status
}

// checkPortAvailability 检查端口可用性
func (bc *BootstrapChecker) checkPortAvailability(configStatus *ConfigStatus) *PortCheckStatus {
	status := &PortCheckStatus{
		Checks: []CheckResult{},
	}

	// 确定要检查的端口
	requestedPort := 8765 // 默认端口
	if configStatus.ConfigFile.Valid && configStatus.HTTPConfig.Valid {
		requestedPort = configStatus.HTTPConfig.Port
	}

	status.RequestedPort = requestedPort

	// 创建端口管理器
	portConfig := &config.PortConfig{
		Port:         requestedPort,
		Host:         "localhost",
		AutoScan:     true,
		ScanRange:    10,
		CheckTimeout: 3,
	}

	if configStatus.ConfigFile.Valid && configStatus.HTTPConfig.Valid {
		portConfig.Host = configStatus.HTTPConfig.Host
		portConfig.AutoScan = configStatus.HTTPConfig.AutoScan
		portConfig.ScanRange = configStatus.HTTPConfig.ScanRange
		portConfig.CheckTimeout = configStatus.HTTPConfig.CheckTimeout
	}

	portManager := config.NewPortManager(portConfig)

	// 检查端口可用性
	finalPort, err := portManager.ResolvePort(0, requestedPort)

	result := CheckResult{
		Name: "端口可用性检查",
	}

	if err != nil {
		result.Status = StatusFail
		result.Message = fmt.Sprintf("端口解析失败: %v", err)
		result.Suggestion = "请检查端口配置或手动指定可用端口"
		status.Available = false
		status.FinalPort = 0
	} else {
		status.Available = true
		status.FinalPort = finalPort
		status.AutoResolved = (finalPort != requestedPort)

		if status.AutoResolved {
			result.Status = StatusWarning
			result.Message = fmt.Sprintf("请求端口 %d 被占用，自动选择端口 %d", requestedPort, finalPort)
			result.Suggestion = "建议更新配置文件使用新端口"
		} else {
			result.Status = StatusPass
			result.Message = fmt.Sprintf("端口 %d 可用", finalPort)
		}
	}

	status.Checks = append(status.Checks, result)

	// 计算端口检查总体状态
	if result.Status == StatusFail {
		status.Overall = StatusFail
	} else if result.Status == StatusWarning {
		status.Overall = StatusWarning
	} else {
		status.Overall = StatusPass
	}

	return status
}

// checkDatabaseInitialization 检查数据库初始化
func (bc *BootstrapChecker) checkDatabaseInitialization(configStatus *ConfigStatus) *DatabaseStatus {
	status := &DatabaseStatus{
		Checks: []CheckResult{},
	}

	// 确定数据路径
	dataPath := "data/vector" // 默认路径
	if configStatus.ConfigFile.Valid && configStatus.VectorConfig.Valid && configStatus.VectorConfig.DataPath != "" {
		dataPath = configStatus.VectorConfig.DataPath
	}

	status.DataPath = dataPath

	// 检查数据目录
	bc.checkDataDirectory(status, dataPath)

	// 检查磁盘空间
	bc.checkDiskSpace(status, dataPath)

	// 检查权限
	bc.checkPermissions(status, dataPath)

	// 模拟数据库连接检查
	bc.checkDatabaseConnection(status, dataPath)

	// 计算数据库检查总体状态
	bc.calculateDatabaseOverallStatus(status)

	return status
}

// checkDataDirectory 检查数据目录
func (bc *BootstrapChecker) checkDataDirectory(status *DatabaseStatus, dataPath string) {
	result := CheckResult{
		Name: "数据目录检查",
	}

	// 检查目录是否存在
	if _, err := os.Stat(dataPath); os.IsNotExist(err) {
		// 尝试创建目录
		if err := os.MkdirAll(dataPath, 0755); err != nil {
			result.Status = StatusFail
			result.Message = fmt.Sprintf("无法创建数据目录 %s: %v", dataPath, err)
			result.Suggestion = "请检查目录权限或手动创建数据目录"
			status.Initialized = false
		} else {
			result.Status = StatusPass
			result.Message = fmt.Sprintf("数据目录 %s 创建成功", dataPath)
			status.Initialized = true
		}
	} else {
		result.Status = StatusPass
		result.Message = fmt.Sprintf("数据目录 %s 已存在", dataPath)
		status.Initialized = true
	}

	status.Checks = append(status.Checks, result)
}

// checkDiskSpace 检查磁盘空间
func (bc *BootstrapChecker) checkDiskSpace(status *DatabaseStatus, dataPath string) {
	result := CheckResult{
		Name: "磁盘空间检查",
	}

	// 简化实现：假设有足够空间
	// 实际实现需要调用系统API获取磁盘空间
	availableSpaceMB := int64(1024) // 假设1GB可用空间
	requiredSpaceMB := int64(100)   // 需要100MB

	if availableSpaceMB >= requiredSpaceMB {
		result.Status = StatusPass
		result.Message = fmt.Sprintf("磁盘空间充足 (%dMB 可用, 需要 %dMB)", availableSpaceMB, requiredSpaceMB)
		status.DiskSpaceOK = true
	} else {
		result.Status = StatusFail
		result.Message = fmt.Sprintf("磁盘空间不足 (%dMB 可用, 需要 %dMB)", availableSpaceMB, requiredSpaceMB)
		result.Suggestion = "请清理磁盘空间或选择其他存储位置"
		status.DiskSpaceOK = false
	}

	status.Checks = append(status.Checks, result)
}

// checkPermissions 检查权限
func (bc *BootstrapChecker) checkPermissions(status *DatabaseStatus, dataPath string) {
	result := CheckResult{
		Name: "目录权限检查",
	}

	// 测试写入权限
	testFile := fmt.Sprintf("%s/.permission_test", dataPath)
	if err := os.WriteFile(testFile, []byte("test"), 0644); err != nil {
		result.Status = StatusFail
		result.Message = fmt.Sprintf("数据目录无写入权限: %v", err)
		result.Suggestion = "请检查目录权限或以管理员身份运行"
		status.PermissionsOK = false
	} else {
		result.Status = StatusPass
		result.Message = "数据目录权限正常"
		status.PermissionsOK = true
		// 清理测试文件
		os.Remove(testFile)
	}

	status.Checks = append(status.Checks, result)
}

// checkDatabaseConnection 检查数据库连接
func (bc *BootstrapChecker) checkDatabaseConnection(status *DatabaseStatus, dataPath string) {
	result := CheckResult{
		Name: "数据库连接检查",
	}

	// 简化实现：模拟数据库连接检查
	// 实际实现需要尝试连接Qdrant Lite
	if status.Initialized && status.DiskSpaceOK && status.PermissionsOK {
		result.Status = StatusPass
		result.Message = "数据库连接正常"
		status.ConnectionOK = true
	} else {
		result.Status = StatusFail
		result.Message = "数据库连接失败"
		result.Suggestion = "请确保数据目录正确初始化"
		status.ConnectionOK = false
	}

	status.Checks = append(status.Checks, result)
}

// calculateDatabaseOverallStatus 计算数据库总体状态
func (bc *BootstrapChecker) calculateDatabaseOverallStatus(status *DatabaseStatus) {
	hasFailure := false
	hasWarning := false

	for _, check := range status.Checks {
		switch check.Status {
		case StatusFail:
			hasFailure = true
		case StatusWarning:
			hasWarning = true
		}
	}

	if hasFailure {
		status.Overall = StatusFail
	} else if hasWarning {
		status.Overall = StatusWarning
	} else {
		status.Overall = StatusPass
	}
}

// calculateOverallStatus 计算总体状态
func (bc *BootstrapChecker) calculateOverallStatus(status *BootstrapStatus) {
	// 检查各个组件的状态
	components := []CheckStatus{
		status.System.Overall,
		status.Dependencies.Overall,
		status.Config.Overall,
		status.PortCheck.Overall,
		status.DatabaseCheck.Overall,
	}

	hasFailure := false
	hasWarning := false

	for _, componentStatus := range components {
		switch componentStatus {
		case StatusFail:
			hasFailure = true
		case StatusWarning:
			hasWarning = true
		}
	}

	if hasFailure {
		status.Overall = StatusFail
		status.ReadyToStart = false
	} else if hasWarning {
		status.Overall = StatusWarning
		status.ReadyToStart = true // 警告不阻止启动
	} else {
		status.Overall = StatusPass
		status.ReadyToStart = true
	}
}

// generateRecommendations 生成建议
func (bc *BootstrapChecker) generateRecommendations(status *BootstrapStatus) {
	recommendations := []string{}

	// 系统建议
	if status.System.Overall == StatusFail {
		recommendations = append(recommendations, "请解决系统环境问题后重新启动")
	}

	// 依赖建议
	if status.Dependencies.Overall == StatusFail {
		recommendations = append(recommendations, "请运行 'go mod tidy' 安装缺失依赖")
	}

	// 配置建议
	if status.Config.Overall == StatusFail {
		recommendations = append(recommendations, "请修复配置文件错误")
	} else if !status.Config.ConfigFile.Exists {
		recommendations = append(recommendations, "建议创建配置文件以自定义服务设置")
	}

	// 端口建议
	if status.PortCheck.AutoResolved {
		recommendations = append(recommendations,
			fmt.Sprintf("建议更新配置文件使用端口 %d", status.PortCheck.FinalPort))
	}

	// 数据库建议
	if status.DatabaseCheck.Overall == StatusFail {
		recommendations = append(recommendations, "请解决数据库初始化问题")
	}

	status.Recommendations = recommendations
}

// logCheckResults 记录检查结果
func (bc *BootstrapChecker) logCheckResults(category string, checks []CheckResult) {
	for _, check := range checks {
		switch check.Status {
		case StatusPass:
			bc.logger.Printf("✅ [%s] %s: %s", category, check.Name, check.Message)
		case StatusWarning:
			bc.logger.Printf("⚠️  [%s] %s: %s", category, check.Name, check.Message)
			if check.Suggestion != "" {
				bc.logger.Printf("   建议: %s", check.Suggestion)
			}
		case StatusFail:
			bc.logger.Printf("❌ [%s] %s: %s", category, check.Name, check.Message)
			if check.Suggestion != "" {
				bc.logger.Printf("   建议: %s", check.Suggestion)
			}
		case StatusSkip:
			bc.logger.Printf("⏭️  [%s] %s: %s", category, check.Name, check.Message)
		}
	}
}

// PrintBootstrapSummary 打印启动摘要
func (bc *BootstrapChecker) PrintBootstrapSummary(status *BootstrapStatus) {
	bc.logger.Println("========================================")
	bc.logger.Println("启动状态校验摘要")
	bc.logger.Println("========================================")

	bc.logger.Printf("校验耗时: %v", status.Duration)
	bc.logger.Printf("总体状态: %s", bc.getStatusEmoji(status.Overall))
	bc.logger.Printf("准备启动: %v", status.ReadyToStart)

	if status.PortCheck.Available {
		bc.logger.Printf("服务端口: %d", status.PortCheck.FinalPort)
	}

	if len(status.Recommendations) > 0 {
		bc.logger.Println("\n建议:")
		for i, rec := range status.Recommendations {
			bc.logger.Printf("  %d. %s", i+1, rec)
		}
	}

	bc.logger.Println("========================================")
}

// SaveBootstrapReport 保存启动报告
func (bc *BootstrapChecker) SaveBootstrapReport(status *BootstrapStatus, filename string) error {
	data, err := json.MarshalIndent(status, "", "  ")
	if err != nil {
		return fmt.Errorf("序列化启动报告失败: %v", err)
	}

	if err := os.WriteFile(filename, data, 0644); err != nil {
		return fmt.Errorf("保存启动报告失败: %v", err)
	}

	bc.logger.Printf("启动报告已保存到: %s", filename)
	return nil
}

// getStatusEmoji 获取状态表情符号
func (bc *BootstrapChecker) getStatusEmoji(status CheckStatus) string {
	switch status {
	case StatusPass:
		return "✅ PASS"
	case StatusWarning:
		return "⚠️ WARNING"
	case StatusFail:
		return "❌ FAIL"
	case StatusSkip:
		return "⏭️ SKIP"
	default:
		return "❓ UNKNOWN"
	}
}
